util = require("util")
assert = require("assert").ok

g_routes = {}  # {router-name: [string, middleware1,middleware2...]}

parse_path = (path) ->
  variables = path.match(/:[a-zA-Z0-9-_.\\]+/g) or []
  re = new RegExp("^" + path.replace(/:[a-zA-Z0-9-_.\\]+/g, "([a-zA-Z0-9-_.\\\\]+)") + "$")
  return [re, (v[1..] for v in variables)]

test_parse_path = () ->
  [re,variables] = parse_path("/foo/:bar/:baz")
  x = re.exec("/foo/bar/baz")
  assert(x?[1] == "bar" && x?[2] == "baz")
  x = re.exec("/foo/12_3/45-6a.\\")
  assert(x?[1] == "12_3" && x?[2] == "45-6a.\\")

make_route = (method,path,middleware_list) ->
  method = method.toUpperCase()
  path_type = null
  if typeof(path) == "string" and path[path.length-1] == "*"    
    path = new RegExp("^" + path[0..path.length-2] + "(.*)$")
    
  if typeof(path) == "string"
    path_type = "string"
    [path_regex,path_variables] = parse_path(path)
  else if path instanceof RegExp
    path_type = "regexp"
    path_regex = path
    path_variables = []
  else
    assert(false, "Wrong path type:#{path}")
    
  return {method,path,middleware_list,path_regex,path_variables,path_type}

route_method = (route) ->
  return route.method  

route_path_type = (route) ->
  return route.path_type
      
route_path = (route) ->
  return route.path

route_middleware_list = (route) ->
  return route.middleware_list

route_path_regex = (route) ->
  return route.path_regex

route_path_variables = (route) ->
  return route.path_variables   

exports.add_route = (name,method,path,middleware_list...) ->
  assert g_routes[name]?, "无效的Router:#{name}"
  g_routes[name].push make_route(method,path,middleware_list)

exports.gfrouter = (name) ->
  
  unless g_routes[name]
    g_routes[name] = []
    
  routes = g_routes[name]
  
  (req,res,next) ->
    # 调试代码，在处理请求前打印日志
    # console.log "access2: `#{req.originalUrl}`#{JSON.stringify req.query}`#{JSON.stringify req.post}" 
    m = null
    for route in routes
      m = route_match(req.method, req.path, route)
      if m != null
        break
    if m != null
      req.params = m
      do_middleware req,res,route_middleware_list(route),next
    else
      next()


rtrim = (path, char) ->
  if typeof(path)=="string" and path.length > 0 and path[path.length-1] == char
    return path[0..path.length-2]
  else
    return path
    

# Match path with route, and return matched parameters as object      
route_match = (method,path,route) ->

  method2 = route_method(route)
  
  unless method == method2 or method2 == "ALL"
    return null

  # trim right '/'
  path = rtrim(path,'/')
  
  re = route_path_regex(route)
  m = re.exec(path)
  if m
    path_type = route_path_type(route)
    if path_type == "string"
      d = {}
      for name,i in route_path_variables(route)
        d[name] = m[i+1]
      return d
    else if path_type == "regexp"
      return m[1..]
    else
      assert(false, "wrong path_type: #{path_type}")
  else
    return null

do_middleware = (req,res,middleware_list,next) ->
  if middleware_list.length == 0
    return next()
  middleware_list[0] req,res, () ->
    do_middleware req,res, middleware_list[1..],next
    
    
  
          
  
